fix(security): harden Milady Docker provisioning against env injection#400
fix(security): harden Milady Docker provisioning against env injection#400
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment Tip You can validate your CodeRabbit configuration file in your editor.If your editor has YAML language server, you can enable auto-completion and validation by adding |
PR Review — fix(security): harden Milady Docker provisioning against env injectionThe core security improvement (centralized uppercase-only key validation + control-character rejection) is sound and worthwhile. Several issues should be addressed before merging. Bugs / Correctness1. Duplicate validation in
const containerName = getContainerName(agentId); // already validates internally
const volumePath = getVolumePath(agentId); // already validates internally
validateContainerName(containerName); // duplicate — remove
validateVolumePath(volumePath); // duplicate — remove2.
// Current — hard to diagnose in production:
throw new Error(`Invalid environment variable value: contains control characters.`);
// Better:
throw new Error(`Invalid environment variable value for key "${key}": contains control characters (newlines and PEM-encoded values are not supported).`);3.
Security4.
Design5. Validation inside factory functions breaks the cleanup path
6. Removed comment was architecturally informative The removed comment block (explaining why Test Coverage Gaps
Nits
Summary
Actionable before merge:
|
Code ReviewOverall this is a solid, well-scoped security hardening PR. The security intent is sound and the implementation is clean. A few issues worth addressing before merging: Bug: Container name length cap is inconsistent with
|
Code ReviewOverall this is a solid security hardening PR — the defense-in-depth approach (validate inputs, then validate derived outputs) is the right call, and the test coverage is good. One real bug and a few smaller items below. Bug: JS
|
Code ReviewOverall this is a well-structured security hardening PR with clear intent and good test coverage. A few issues worth addressing before merge. Bugs / Correctness1. // docker-sandbox-utils.ts:107
if (hasControlChars(containerName) || !/^[a-zA-Z0-9][a-zA-Z0-9_.-]{0,127}$/.test(containerName)) {The character class 2. Silent max-length reduction for
3.
However, Security4. // docker-sandbox-provider.ts:334
shellQuote(resolvedImage),Docker image names with 5. Validation placement in The double-validation (calling Test Coverage Gaps6. Missing edge case: empty string env key
7. Missing edge case: root path
test("rejects root path", () => {
expect(() => validateVolumePath("/")).toThrow(/Invalid volume path/);
});8. The PR description lists Nits
SummaryThe core security fix is correct and well-implemented. The centralized helpers, test coverage, and defense-in-depth double-validation are all solid. The two items I'd prioritize before merge:
The redundant |
|
First section of review posted |
Code ReviewGood security hardening overall. The centralized validation approach is the right architecture — replacing ad-hoc inline checks with shared helpers reduces the chance of future bypass. Test coverage is solid. A few issues worth addressing: Bug: validateContainerName one-char min vs. Docker's actual limitThe regex accepts 1-char names (e.g. 'm'), but Docker actually requires a minimum of 2 characters. The container name 'm' would be rejected at the Docker API level after passing your validator. Adjust the second group from {0,127} to {1,127} to enforce a 2-128 char range. Redundant hasControlChars before regex in four validatorsvalidateAgentId, validateEnvKey, validateContainerName, and validateVolumePath all call hasControlChars before a regex that already rejects those same characters. The guard is never false when the regex would pass. This is not wrong — it is defense-in-depth — but it could confuse future maintainers. Either remove the redundant calls or add a comment noting the intentional layering. validateVolumePath misses PATH_MAX (informational)Given that agentId is bounded by MAX_AGENT_ID_LENGTH = 121 and the prefix is /data/agents/ (13 chars), the max possible path is 134 chars — well within PATH_MAX (4095). No fix needed, but a comment here would guard against future prefix changes silently reopening this. Missing test: empty string for validateContainerNameThe suite covers shell metacharacters, trailing newlines, and length overflow, but not the empty-string case. The regex implicitly rejects it (the anchor requires at least one char), but an explicit test documents that expectation. milady-create-routes.test.ts referenced in validation but not in the diffThe PR description lists that file as a validation step, but it is not in the diff. If the new validators propagate differently at the route level, integration coverage should be in the PR. If the file was run but unchanged, a note clarifying that would help reviewers. Minor: validateEnvValue error message is misleading for non-PEM control charsThe message always says 'newlines and PEM-encoded values are not supported', but it fires for any control character including null bytes and tabs. A more precise message would reference control characters 0x00-0x1f and 0x7f rather than only mentioning newlines. Nit: escaped hyphen in validateVolumePath regexThe backslash-hyphen is valid but the conventional form places the literal hyphen at the end of the character class. Avoids potential confusion with a character range. OverallThe security intent is sound, the tradeoff (uppercase-only env keys, no control chars in values) is clearly documented, and validation is correctly applied before shell interpolation. The getContainerName/getVolumePath double-validation guardrail is a nice defensive touch. The Docker 1-char minimum discrepancy and the missing empty-string test are the only items worth fixing before merge. |
Summary
This PR hardens the Milady Docker provisioning path against command injection in the remote
docker runflow.Security impact
This addresses a critical authenticated RCE risk in provisioning: user-controlled environment variables were being assembled into a remote shell command for
docker run. While values were shell-quoted, validation was incomplete and the provisioning path still relied on shell interpolation for multiple user-derived fields.Changes
^[A-Z_][A-Z0-9_]*$docker-sandbox-providerwith centralized helpersNotes
Validation
bun test packages/tests/unit/docker-infrastructure.test.tsbun test packages/tests/unit/milady-create-routes.test.tscodex review --uncommitted(flagged the tighter env validation as behavior-changing; retained intentionally for security hardening)Risk
High security value, low code-surface change. Main behavior change is stricter validation of user-supplied env vars during Docker provisioning.